package org.tokaf.rater;

import org.tokaf.TopKElement;
import org.tokaf.datasearcher.DataSearcher;

/**
 * <p>WeightDegreeAverage computes the rating as x^ix*wx+y^iy*wy+../wx+wy+.....
 * It is like weight average except that the ratings are raised to theid ix-th power. 
 * </p>
 * <p>Copyright (c) 2006</p>
 * @author Alan Eckhardt
 * @version 1.0
 */
public class WeightDegreeAverage extends WeightAverage {
	// Jakou vahu tomu kteremu poli prirazuji
	double weights[];

	// Jaky exponent tomu kteremu poli prirazuji
	double exponents[];

	public WeightDegreeAverage(double exponents[]) {
		super();
		this.exponents = (double[]) exponents.clone();
	}

	public WeightDegreeAverage(String names[], double weights[],
			double exponents[]) {
		super(names, weights);
		this.weights = (double[]) weights.clone();
		this.exponents = (double[]) exponents.clone();
		this.fields = (String[]) names.clone();
	}

	public double getDerivation(int index, DataSearcher data[], TopKElement el) {
		if (weights != null && weights.length > index) {
			double a = weights[index] * exponents[index];
			double b = Math.pow(data[index].getNormalizer()
					.Normalize(el, index), exponents[index] - 1);
			return a * b;
		}
		return -1;
	}

	public double getDerivation(int index, DataSearcher data[], Object[] datas) {
		if (weights != null && weights.length > index) {
			// Derivace a^b*x je a*(b-1)*x^(b-1)
			// Tohle je slozka a*(b-1)
			double a = weights[index] * exponents[index];
			// Tohle je slozka x^(b-1)
			double b = Math.pow(data[index].getNormalizer().Normalize(
					datas[index]), exponents[index] - 1);
			return a * b;
		}
		return -1;
	}

	public double getWeight(int i) {
		if (weights != null && weights.length > i)
			return weights[i];
		return -1;
	}

	public double getRating(TopKElement el, DataSearcher data[],
			TopKElement threshold) {

		double res = 0;
		double divider = 0;
		for (int i = 0; i < el.getLength(); i++) {
			divider += weights[i];
			if (el.isNull(i))
				res += Math.pow(threshold.getRating(i), exponents[i])
						* weights[i];
			else
				res += Math.pow(el.getRating(i), exponents[i]) * weights[i];
		}
		return res;
	}

	public double getRating(TopKElement el, DataSearcher data[], double optional) {
		double res = 0;
		double divider = 0;
		for (int i = 0; i < el.getLength(); i++) {
			divider += weights[i];
			if (el.isNull(i))
				res += optional;
			else
				res += Math.pow(el.getRating(i), exponents[i]) * weights[i];
		}
		return res;
	}

}
